// 此文件在app.ts前初始化，不允许使用app.ts，axios.js
import axios from 'axios'; // 这里必须用 axios，而不能用 @/axios
import webConfig from '@/configs/web-config';
import { reactive } from 'vue';
import { useMenus } from '@/routers/menu-service';

interface Role {
    Name: string,
    DisplayName: string,
    Menus: any[],
    NotSetEquals: number,
    DepartName: string,
    ForDepart: string,
    Permissions: string[]
}

interface CurrentUser {
    RealName: string,
    Avatar: string,
    Code: string,
    Roles: Role[],
    currentRole: Role,
    currentRoleIndex: number,
    switchRole: (nv : number) => void,
    succeed (permissionOrMenu : string) : Boolean,
    getRole (role : string) : Role | undefined,
    ver: number
}

const requestKey = webConfig.requestKey;
localStorage.setItem("requestKey", requestKey);
const alphabets = "abcdefghijklmnopqrstuvwxyz";
const defaultRole : Role = { "Name": "匿名用户", "DisplayName": "匿名用户", DepartName: "", ForDepart: "", NotSetEquals: -1, "Permissions": [], "Menus": [] };

let accessToken = {
    requestKey, 
    token: ""
}

let currentUser: CurrentUser = reactive({ 
    "Code": "", 
    "RealName": "测试", 
    "Avatar": "", 
    "Roles": [ defaultRole ],
    currentRole: defaultRole,
    currentRoleIndex: 0,
    switchRole,
    succeed,
    getRole,
    ver: 0,
});
let token = "";
let isLogined = false;

function succeed (permissionOrMenu : string) : Boolean {
    let r = currentUser.currentRole;
    if (r.Permissions.indexOf(permissionOrMenu) > -1) return true;
    // if (currentUser.Roles.find(e => e.Name == permissionOrMenu)) return true;

    return r.NotSetEquals === 0 || !!r.Menus.find(e => { return e.path === permissionOrMenu || (e.children as any[]).find(x => x.path === permissionOrMenu) });
}

function getRole (role : string) : Role | undefined {
    return currentUser.Roles.find(e => e.Name == role);
}

function switchRole (nv : number) {
    currentUser.currentRoleIndex = nv;
    currentUser.currentRole = currentUser.Roles.length > nv ? currentUser.Roles[nv] : defaultRole;
    accessToken.token = token +  alphabets[nv];
    localStorage.setItem(requestKey, accessToken.token);
    useMenus(currentUser.currentRole.Menus);
    currentUser.ver++;
}

function setCurrentUser(msg: any) {
    if (!msg.success) {
        isLogined = false;
        return;
    }

    Object.assign(currentUser, msg.data);
    token = (msg.token as string);
    let index: number = alphabets.indexOf(token.charAt(token.length - 1));
    token = token.slice(0, token.length - 1);
    switchRole(index);
    isLogined = true;
}

async function validateCurrentUser () {
    accessToken.token = localStorage.getItem(requestKey) || "";
    token = accessToken.token.slice(0, token.length - 1);
    let msg = await axios.post<any, any>("/api/authorize/ValidateToken", {}, {
        headers: {
            [accessToken.requestKey]: accessToken.token
        }
    });
    msg = msg.data;
    // let msg = await axios.post<any, any>("/debug/security/ValidateToken");
    
    if (msg.success) {
        setCurrentUser(msg);
    } else {        
        isLogined = false;
    }

    return isLogined;
}

async function logout () {
    await axios.post("/api/authorize/logout", {}, {
        headers: {
            [accessToken.requestKey]: accessToken.token
        }
    });
    isLogined = false;
}

export {
    currentUser,
    accessToken,
    switchRole,
    setCurrentUser,
    validateCurrentUser,
    isLogined,
    logout
}

export type {
    Role,
    CurrentUser,
}